﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using SMSPanasonic.Business;

namespace SMSPanasonic
{
    class SMSTask
    {
        private int _thread_id;
        private bool _serviceStarted;

        private int _interval = Properties.Settings.Default.IntevalDefault;
        private int _interval_thread_fail = Properties.Settings.Default.IntervalTheadFail;
        private int _interval_thread_timeout = Properties.Settings.Default.IntervalThreadTimeOut;

        private EventLog _serviceEventLog;
        private bool _thread_working_flag = false;
        private int _retry_on_fail_req_times;
        private long _retry_on_fail_req_duration;
        private int _retry_on_time_out_req_times;
        private long _retry_on_time_out_req_duration;

        private string _status_pending;
        private string _status_pending_proccessing;

        private string _status_fail;
        private string _status_fail_proccessing;

        private string _status_timeout;
        private string _status_timeout_proccessing;

        private SmsRouter _sms_router;
        private static Dictionary<int, DateTime> smsRouterWarningTime = new Dictionary<int, DateTime>();
        private static int[] usingResource = new int[PanasonicService.MTRouterList.Count];
        private static Dictionary<int, int> smsRouterIDMapArray = new Dictionary<int, int>();

        static SMSTask()
        {
            //smsBranchName.Timeout = Properties.Settings.Default.ServiceTimeOut;
            int iOrder = 0;
            foreach (SmsRouter itemRouter in PanasonicService.MTRouterList)
            {
                usingResource[iOrder] = 0;
                smsRouterIDMapArray.Add(itemRouter.RouterID.Value, iOrder);
                iOrder += 1;
            }
        }

        public SMSTask(int thread_id, SmsRouter sms_router, EventLog serviceEventLog)
        {
            this._sms_router = sms_router;
            this._thread_id = thread_id;
            this._serviceEventLog = serviceEventLog;
        }

        public bool ServiceStarted
        {
            get
            {
                return _serviceStarted;
            }
            set
            {
                _serviceStarted = value;
            }
        }
        public int Interval
        {
            get
            {
                return _interval;
            }
            set
            {
                _interval = value;
            }
        }
        public int RetryOnFailReqTimes
        {
            get
            {
                return _retry_on_fail_req_times;
            }
            set
            {
                _retry_on_fail_req_times = value;
            }
        }
        public long RetryOnFailReqDuration
        {
            get
            {
                return _retry_on_fail_req_duration;
            }
            set
            {
                _retry_on_fail_req_duration = value;
            }
        }
        public int RetryOnTimeOutReqTimes
        {
            get
            {
                return _retry_on_time_out_req_times;
            }
            set
            {
                _retry_on_time_out_req_times = value;
            }
        }
        public long RetryOnTimeOutReqDuration
        {
            get
            {
                return _retry_on_time_out_req_duration;
            }
            set
            {
                _retry_on_time_out_req_duration = value;
            }
        }

        public string StatusPending
        {
            get
            {
                return _status_pending;
            }
            set
            {
                _status_pending = value;
            }
        }

        public string StatusPendingProccessing
        {
            get
            {
                return _status_pending_proccessing;
            }
            set
            {
                _status_pending_proccessing = value;
            }
        }

        public string StatusFail
        {
            get
            {
                return _status_fail;
            }
            set
            {
                _status_fail = value;
            }
        }
        public string StatusFailProccessing
        {
            get
            {
                return _status_fail_proccessing;
            }
            set
            {
                _status_fail_proccessing = value;
            }
        }
        public string StatusTimeOut
        {
            get
            {
                return _status_timeout;
            }
            set
            {
                _status_timeout = value;
            }
        }
        public string StatusTimeOutProccessing
        {
            get
            {
                return _status_timeout_proccessing;
            }
            set
            {
                _status_timeout_proccessing = value;
            }
        }

        public void ExecuteTask()
        {
            DateTime lastRunTime = DateTime.Now;
            DateTime lastRunFailThreadTime = DateTime.Now;
            DateTime lastRunTimeoutThreadTime = DateTime.Now;
            bool pending_running = false;

            // TODO: Add code here to start your service.
            //_serviceEventLog.WriteEntry("SMSPanasonicMTRouter service started=>Thread: " + this._thread_id.ToString() + "; RouterID: " + (this._sms_router.RouterID.IsNull ? "" : this._sms_router.RouterID.Value.ToString()) + "; RouterName: " + (this._sms_router.RouterName.IsNull ? "" : this._sms_router.RouterName.Value), EventLogEntryType.Information);
            while (_serviceStarted)
            {
                // check the current time against the last run plus interval
                if (((TimeSpan)(DateTime.Now.Subtract(lastRunTime))).TotalMilliseconds >= _interval && !_thread_working_flag)
                {
                    _thread_working_flag = true;
                    try
                    {
                        List<SmsMtWaiting> smsMtWaitingList = new List<SmsMtWaiting>();
                        string url_alive = "";
                        if (Common.isDatabaseAlive(Properties.Settings.Default.ConnectionString) == System.Data.ConnectionState.Open)
                        {
                            if (SmsMtWaiting.GetCount(" 1=1 ") > 0)
                            {
                                //Kiem tra router con song khong truoc khi goi
                                if (Common.WebSerivceIsAvailable(this._sms_router, ref url_alive))
                                {
                                    //Khoa resource, chi cho 1 RouterID Thread truy cap de tranh bi trung lap
                                    //Neu trang thai van la 1 thi doi
                                    while (0 != Interlocked.Exchange(ref usingResource[smsRouterIDMapArray[this._sms_router.RouterID.Value]], 1))
                                    {
                                        Thread.Sleep(50);
                                    }

                                    smsMtWaitingList = SmsMtWaiting.GetForRouterExecute(Properties.Settings.Default.MTBatchSize);
                                    pending_running = true;

                                    //Release the lock
                                    Interlocked.Exchange(ref usingResource[smsRouterIDMapArray[this._sms_router.RouterID.Value]], 0);
                                    if (smsMtWaitingList.Count > 0)
                                    {
                                        SMSMTSend smsMTSend = new SMSMTSend(this._sms_router, this._thread_id, this._retry_on_fail_req_duration, this._retry_on_time_out_req_duration, this._retry_on_fail_req_times, this._retry_on_time_out_req_times);
                                        smsMTSend.RouterURL = url_alive;
                                        smsMTSend.SendSms(smsMtWaitingList);
                                    }
                                }
                                else
                                {
                                    //Thong bao Router da die, khong the ket noi duoc
                                    if (!smsRouterWarningTime.ContainsKey(this._sms_router.RouterID.Value))
                                    {
                                        smsRouterWarningTime.Add(this._sms_router.RouterID.Value, DateTime.Now);
                                        //Dua ra thong bao 10 phut 1 lan
                                        Logs logs = new Logs();
                                        logs.LogSource = System.Data.SqlTypes.SqlString.Null;
                                        logs.LogMessage = "ERROR-SMSPanasonicRouter(" + this._sms_router.RouterName + ") Thread:" + this._thread_id.ToString() + "=> " + "Khong ket noi duoc server:URL:" + (this._sms_router.RouterURL.IsNull ? "" : this._sms_router.RouterURL.Value) + (this._sms_router.RouterURL2.IsNull ? "" : ";" + this._sms_router.RouterURL2.Value);
                                        logs.LogTime = DateTime.Now;
                                        logs.LogTrace = System.Data.SqlTypes.SqlString.Null;
                                        logs.LogType = "MTROUTER";
                                        logs.Status = new System.Data.SqlTypes.SqlBoolean(true);
                                        logs.Save();
                                    }
                                    else
                                    {
                                        if (((TimeSpan)(DateTime.Now.Subtract(smsRouterWarningTime[this._sms_router.RouterID.Value]))).TotalMinutes > Properties.Settings.Default.IntervalSystemAlert)
                                        {
                                            //Dua ra thong bao 10 phut 1 lan
                                            Logs logs = new Logs();
                                            logs.LogSource = System.Data.SqlTypes.SqlString.Null;
                                            logs.LogMessage = "ERROR-SMSPanasonicRouter(" + this._sms_router.RouterName + ") Thread:" + this._thread_id.ToString() + "=> " + "Khong ket noi duoc server:URL:" + (this._sms_router.RouterURL.IsNull ? "" : this._sms_router.RouterURL.Value) + (this._sms_router.RouterURL2.IsNull ? "" : ";" + this._sms_router.RouterURL2.Value);
                                            logs.LogTime = DateTime.Now;
                                            logs.LogTrace = System.Data.SqlTypes.SqlString.Null;
                                            logs.LogType = "MTROUTER";
                                            logs.Status = new System.Data.SqlTypes.SqlBoolean(true);
                                            logs.Save();
                                            smsRouterWarningTime[this._sms_router.RouterID.Value] = DateTime.Now;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    catch (Exception ext)
                    {
                        _serviceEventLog.WriteEntry(ext.Message, EventLogEntryType.Error);
                    }
                    finally
                    {
                        _thread_working_flag = false;
                    }

                    if (pending_running)
                    {
                        lastRunTime = DateTime.Now;
                        pending_running = false;
                    }
                }

                // yield
                if (_serviceStarted)
                {
                    Thread.Sleep(new TimeSpan(0, 0, 0, 0, 100));
                }
            }
            _serviceEventLog.WriteEntry("SMSPanasonicMTRouter service stoped=>Thread: " + this._thread_id.ToString() + "; RouterID: " + (this._sms_router.RouterID.IsNull ? "" : this._sms_router.RouterID.Value.ToString()) + "; RouterName: " + (this._sms_router.RouterName.IsNull ? "" : this._sms_router.RouterName.Value), EventLogEntryType.Information);
            Thread.CurrentThread.Abort();
        }

    }
}
